package org.jeecg.modules.demo.ipds.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jeecg.common.util.Md5Util;
import org.jeecg.common.util.MinioUtil;
import org.jeecg.modules.demo.ipds.entity.*;
import org.jeecg.modules.demo.ipds.entity.dto.XmlFileDto;
import org.jeecg.modules.demo.ipds.entity.vo.BitListVo;
import org.jeecg.modules.demo.ipds.entity.vo.IpTreeVo;
import org.jeecg.modules.demo.ipds.entity.vo.SpecKeyValueDO;
import org.jeecg.modules.demo.ipds.entity.vo.TreeByteListVo;
import org.jeecg.modules.demo.ipds.mapper.XmlListMapper;
import org.jeecg.modules.demo.ipds.service.*;
import org.jeecg.modules.demo.util.DocumentUtil;
import org.jeecg.modules.demo.util.XmlBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Random;

/**
 * @Description: 导出xml表
 * @Author: jeecg-boot
 * @Date:   2024-04-06
 * @Version: V1.0
 */
@Service
public class XmlListServiceImpl extends ServiceImpl<XmlListMapper, XmlList> implements IXmlListService {
    @Autowired
    private IIpTreeService ipTreeService;

    @Autowired
    private ITreeByteListService treeByteListService;

    @Autowired
    private IBitListService bitListService;


    @Autowired
    private IMyIpWrodService iMyIpWrodService;

    @Autowired
    private IByteFrameZuService byteFrameZuService;

    @Autowired
    private ITreeByteListService2 treeByteListService2;

    @Override
    public String createXml(String wordId,String ipTreeId) {

        IpTree ipTree = ipTreeService.getById(ipTreeId);
        MyIpWrod IpWord = iMyIpWrodService.getById(ipTree.getWordId());
        if (!ipTree.getType().equals("协议")){
            return "章节不支持生成xml";
        }
        String ipName = IpWord.getIpName()+ipTree.getSectionName();

        try {
            // 创建解析器工厂
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = factory.newDocumentBuilder();
            Document document = db.newDocument();
            // 不显示standalone="no"
            document.setXmlStandalone(true);
            // 创建文档
            Element bookstore = document.createElement("File");

            // 协议文档名
            bookstore.setAttribute("Name", ipName);
            String checksum = getChecksum();


            String sectionName = ipTree.getSectionName();

            // 创建协议
            Element Protocol = document.createElement("Protocol");
            //协议名
            Protocol.setAttribute("sectionName", sectionName);
//            Protocol.setAttribute("id", ipTreeId);

            QueryWrapper<TreeByteList> treeByteListQueryWrapper = new QueryWrapper<>();
            treeByteListQueryWrapper.eq("ip_tree_id", ipTreeId);
            List<TreeByteList> treeByte = treeByteListService.list(treeByteListQueryWrapper);
            //创建字节
            //创建字节
            for (TreeByteList treeByteList : treeByte) {


                String ByteId = treeByteList.getId();
                Element ByteItem = document.createElement("ByteItem");
                setByteElement(ByteItem,treeByteList);

                Protocol.appendChild(ByteItem);
                QueryWrapper<BitList> bitListQueryWrapper = new QueryWrapper<>();
                bitListQueryWrapper.eq("byte_id",ByteId);
                bitListQueryWrapper.orderByAsc("index_sx");
                List<BitList> bitlist = bitListService.list(bitListQueryWrapper);
                for (BitList bitList : bitlist) {

                    Element bitItem = document.createElement("BitItem");
                    setBitElement(bitItem,bitList);
                    ByteItem.appendChild(bitItem);

                }
                QueryWrapper<ByteFrameZu> byteFrameZuQueryWrapper = new QueryWrapper<>();
                byteFrameZuQueryWrapper.eq("byte_id",ByteId);
                byteFrameZuQueryWrapper.orderByAsc("index_sx");
                List<ByteFrameZu>  byteFrameZus= byteFrameZuService.list(byteFrameZuQueryWrapper);
                for (ByteFrameZu frameZus : byteFrameZus) {

                    String zuId = frameZus.getId();
                    Element subframeItem = document.createElement("SubframeItem");

                    subframeItem.setAttribute("name",frameZus.getName());
                    subframeItem.setAttribute("indexSx",frameZus.getIndexSx().toString());
                    ByteItem.appendChild(subframeItem);

                    QueryWrapper<TreeByteList2> treeByteList2QueryWrapper = new QueryWrapper<>();
                    treeByteList2QueryWrapper.eq("pid",zuId);
                    treeByteList2QueryWrapper.orderByAsc("index_sx");
                    List<TreeByteList2> byte2List = treeByteListService2.list(treeByteList2QueryWrapper);

                    for (TreeByteList2 treeByteList2 : byte2List) {
                        Element ByteItem2 = document.createElement("ByteItem");
                        setByte2Element(ByteItem2,treeByteList2);
                        subframeItem.appendChild(ByteItem2);

                        String id = treeByteList2.getId();
                        QueryWrapper<BitList> bitListQueryWrapper2 = new QueryWrapper<>();
                        bitListQueryWrapper2.eq("byte_id",id);
                        bitListQueryWrapper2.orderByAsc("index_sx");
                        List<BitList> bitlist2 = bitListService.list(bitListQueryWrapper2);
                        for (BitList bitList : bitlist2) {

                            Element bitItem2 = document.createElement("BitItem");

                            setBitElement(bitItem2,bitList);


                            ByteItem2.appendChild(bitItem2);

                        }

                    }
                }

            }
            bookstore.appendChild(Protocol);
            document.appendChild(bookstore);

            String upload = setElementUploadFileUrl(document,ipName,checksum);
            return upload ;
        } catch (Exception e) {
            e.printStackTrace();

        }
        return null;
    }

    public void setBitElement( Element bitItem2 ,BitList bitList) throws JsonProcessingException {
//        bitItem2.setAttribute("ID", bitList.getId());
//        bitItem2.setAttribute("ByteId",bitList.getByteId());
        bitItem2.setAttribute("annotation",bitList.getAnnotation());
        bitItem2.setAttribute("startBit", String.valueOf(bitList.getStartBit()));
        bitItem2.setAttribute("endBit", String.valueOf(bitList.getEndBit()));
        bitItem2.setAttribute("defaultValue",bitList.getDefaultValue());
        bitItem2.setAttribute("bitLength",bitList.getBitLength());
        bitItem2.setAttribute("bitName",bitList.getBitName());
        bitItem2.setAttribute("valueScope",bitList.getValueScope());
//        bitItem2.setAttribute("reuseField",bitList.getReuseFieldString());
        bitItem2.setAttribute("unit",bitList.getUnit());
        bitItem2.setAttribute("indexSx",bitList.getIndexSx().toString());
        bitItem2.setAttribute("resolutionRatio",bitList.getResolutionRatio());
        bitItem2.setAttribute("resolutionRatioLength",bitList.getResolutionRatioLength().toString());
        if (bitList.getExtendField()==null) {
            bitItem2.setAttribute("extendField", "[]");
        }else {
//            Object parse = JSONObject.parse(bitList.getExtendField().toString());
            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(bitList.getExtendField());
            bitItem2.setAttribute("extendField",json );
        }


    }


    public void setByteElement( Element ByteItem ,TreeByteList treeByteList ) throws JsonProcessingException {
//        ByteItem.setAttribute("id", treeByteList.getId());
        ByteItem.setAttribute("byteName", treeByteList.getByteName());
        ByteItem.setAttribute("sn", treeByteList.getSn());
        ByteItem.setAttribute("dataType", treeByteList.getDataType());
        ByteItem.setAttribute("valueScope",treeByteList.getValueScope());
        ByteItem.setAttribute("resolutionRatio",treeByteList.getResolutionRatio());
        ByteItem.setAttribute("resolutionRatioLength",treeByteList.getResolutionRatioLength().toString());
        ByteItem.setAttribute("isSymbolString",treeByteList.getIsSymbolString());
        ByteItem.setAttribute("fieldType",treeByteList.getFieldType());
        ByteItem.setAttribute("fieldTypeValue",treeByteList.getFieldTypeValue());
        ByteItem.setAttribute("defaultValue",treeByteList.getDefaultValue());
        ByteItem.setAttribute("unit",treeByteList.getUnit());
        ByteItem.setAttribute("reuseField",treeByteList.getReuseField());
        ByteItem.setAttribute("fieldLength",treeByteList.getFieldLength());
        if (treeByteList.getExtendField()==null) {
            ByteItem.setAttribute("extendField", "[]");
        }else {
          ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(treeByteList.getExtendField());
            ByteItem.setAttribute("extendField", json);
        }

//        ByteItem.setAttribute("tableType",treeByteList.getTableType());
        ByteItem.setAttribute("indexSx",treeByteList.getIndexSx().toString());
    }


   public void setByte2Element(Element ByteItem2,TreeByteList2 treeByteList2) throws JsonProcessingException {
       ByteItem2.setAttribute("byteName", treeByteList2.getByteName());
       ByteItem2.setAttribute("sn", treeByteList2.getSn());
       ByteItem2.setAttribute("dataType", treeByteList2.getDataType());
       ByteItem2.setAttribute("valueScope",treeByteList2.getValueScope());
       ByteItem2.setAttribute("resolutionRatio",treeByteList2.getResolutionRatio());
       ByteItem2.setAttribute("resolutionRatioLength",treeByteList2.getResolutionRatioLength().toString());
       ByteItem2.setAttribute("isSymbolString",treeByteList2.getIsSymbolString());
       ByteItem2.setAttribute("fieldType",treeByteList2.getFieldType());
       ByteItem2.setAttribute("fieldTypeValue",treeByteList2.getFieldTypeValue());
       ByteItem2.setAttribute("defaultValue",treeByteList2.getDefaultValue());
       ByteItem2.setAttribute("unit",treeByteList2.getUnit());
       ByteItem2.setAttribute("reuseField",treeByteList2.getReuseField());
       ByteItem2.setAttribute("fieldLength",treeByteList2.getFieldLength());
       if (treeByteList2.getExtendField()==null) {
           ByteItem2.setAttribute("extendField", "[]");
       }else {
           ObjectMapper objectMapper = new ObjectMapper();
           String json = objectMapper.writeValueAsString(treeByteList2.getExtendField());
           ByteItem2.setAttribute("extendField", json);
       }

       ByteItem2.setAttribute("indexSx",treeByteList2.getIndexSx().toString());
   }

   public String setElementUploadFileUrl(Document document,String ipName,String checksum) throws Exception {
       String string = DocumentUtil.doc2FormatString(document);


       String chick = Md5Util.md5Encode(string, "utf-8");
//          
//          



       //			 创建TransformerFactory对象
       TransformerFactory tff = TransformerFactory.newInstance();
       // 创建 Transformer对象
       Transformer tf = tff.newTransformer();

       // 输出内容是否使用换行
       tf.setOutputProperty(OutputKeys.INDENT, "yes");
       String fileName= ipName+checksum+".xml";

       ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
       // 创建xml文件并写入内容
       tf.transform(new DOMSource(document), new StreamResult(outputStream));
       InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());



         String upload = MinioUtil.upload(inputStream, fileName);
         XmlList xmlList = new XmlList();
         xmlList.setChecksum(chick);
         xmlList.setFileName(fileName);
         xmlList.setXmlUrl(upload);
         this.baseMapper.insert(xmlList);


        return upload;
   }
    @Override
    public String createXml(String wordId) {
        MyIpWrod IpWord = iMyIpWrodService.getById(wordId);
        String ipName = IpWord.getIpName();

        try {
            // 创建解析器工厂
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = factory.newDocumentBuilder();
            Document document = db.newDocument();
            // 不显示standalone="no"
            document.setXmlStandalone(true);
            // 创建文档
            Element bookstore = document.createElement("File");
            // 协议文档名
            String checksum = getChecksum();
            bookstore.setAttribute("Name", ipName);

            QueryWrapper<IpTree> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("word_id", wordId);
            queryWrapper.eq("type", "协议");
            List<IpTree> list = ipTreeService.list(queryWrapper);

            for (IpTree ipTree : list) {
                String sectionName = ipTree.getSectionName();
                String ipTreeId = ipTree.getId();
                // 创建协议
                Element Protocol = document.createElement("Protocol");
                //协议名
                Protocol.setAttribute("sectionName", sectionName);
                QueryWrapper<TreeByteList> treeByteListQueryWrapper = new QueryWrapper<>();
                treeByteListQueryWrapper.eq("ip_tree_id", ipTreeId);
                treeByteListQueryWrapper.orderByAsc("index_sx");
                List<TreeByteList> treeByte = treeByteListService.list(treeByteListQueryWrapper);
                //创建字节
                for (TreeByteList treeByteList : treeByte) {


                    String ByteId = treeByteList.getId();
                    Element ByteItem = document.createElement("ByteItem");
                    //设置字节文件
                    setByteElement(ByteItem,treeByteList);

                    Protocol.appendChild(ByteItem);
                    QueryWrapper<BitList> bitListQueryWrapper = new QueryWrapper<>();
                    bitListQueryWrapper.eq("byte_id",ByteId);
                    bitListQueryWrapper.orderByAsc("index_sx");
                    List<BitList> bitlist = bitListService.list(bitListQueryWrapper);
                    for (BitList bitList : bitlist) {

                        Element bitItem = document.createElement("BitItem");
                       setBitElement(bitItem,bitList);
                        ByteItem.appendChild(bitItem);

                    }
                    QueryWrapper<ByteFrameZu> byteFrameZuQueryWrapper = new QueryWrapper<>();
                    byteFrameZuQueryWrapper.eq("byte_id",ByteId);
                    byteFrameZuQueryWrapper.orderByAsc("index_sx");
                    List<ByteFrameZu>  byteFrameZus= byteFrameZuService.list(byteFrameZuQueryWrapper);
                    for (ByteFrameZu frameZus : byteFrameZus) {

                        String zuId = frameZus.getId();
                        Element subframeItem = document.createElement("SubframeItem");

                        subframeItem.setAttribute("name",frameZus.getName());
                        subframeItem.setAttribute("indexSx",frameZus.getIndexSx().toString());
                        ByteItem.appendChild(subframeItem);

                        QueryWrapper<TreeByteList2> treeByteList2QueryWrapper = new QueryWrapper<>();
                        treeByteList2QueryWrapper.eq("pid",zuId);
                        treeByteList2QueryWrapper.orderByAsc("index_sx");
                        List<TreeByteList2> byte2List = treeByteListService2.list(treeByteList2QueryWrapper);

                        for (TreeByteList2 treeByteList2 : byte2List) {
                            Element ByteItem2 = document.createElement("ByteItem");

                            setByte2Element(ByteItem2,treeByteList2);

                            subframeItem.appendChild(ByteItem2);

                            String id = treeByteList2.getId();
                            QueryWrapper<BitList> bitListQueryWrapper2 = new QueryWrapper<>();
                            bitListQueryWrapper2.eq("byte_id",id);
                            bitListQueryWrapper2.orderByAsc("index_sx");
                            List<BitList> bitlist2 = bitListService.list(bitListQueryWrapper2);
                            for (BitList bitList : bitlist2) {

                                Element bitItem2 = document.createElement("BitItem");

                                setBitElement(bitItem2,bitList);
                                ByteItem2.appendChild(bitItem2);

                            }

                        }
                    }

                }

                bookstore.appendChild(Protocol);

            }
            document.appendChild(bookstore);

            //document转md5

            String upload = setElementUploadFileUrl(document,ipName,checksum);

            return upload ;
        } catch (Exception e) {
            e.printStackTrace();

        }
        return null;
    }

    @Override
    public boolean importXml(HttpServletRequest request, HttpServletResponse response) throws ParserConfigurationException, IOException, SAXException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");// 获取上传文件对象
        String wordId = request.getParameter("id");
//
//        System.out.println(wordId);
        if (wordId==null){
            log.error("wordId为空");
            return false;
        }
//        System.out.println(file);
            // 创建DocumentBuilderFactory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document parseDocument = builder.parse(file.getInputStream());
            String stringXml = DocumentUtil.doc2FormatString(parseDocument);




            //判断校验是否成功
            boolean check = check(stringXml);

            if (check){
                XmlFileDto xmlFileDto = (XmlFileDto) XmlBuilder.JAXB_XmlToBean(XmlFileDto.class, stringXml);
                for (IpTreeVo ipTreeVo : xmlFileDto.getProtocol()) {
                    IpTree ipTree = new IpTree();
                    String name = ipTreeVo.getName();
                    ipTree.setSectionName(name);
                    ipTree.setType("协议");
                    ipTree.setPid("0");
                    ipTree.setWordId(wordId);
                    ipTreeService.save(ipTree);
                    //新增后的Id
                    String ipTreeId = ipTree.getId();


                    //第一个协议
                    List<TreeByteListVo> byteListList = ipTreeVo.getByteListList();

                    for (TreeByteListVo treeByteListVo : byteListList) {
                        treeByteListVo.setIpTreeId(ipTreeId);
                        List<SpecKeyValueDO> specKeyValueDOS = JSONObject.parseArray(treeByteListVo.getExtendField(), SpecKeyValueDO.class);
                        TreeByteList treeByteList = new TreeByteList(treeByteListVo,specKeyValueDOS);
                        treeByteListService.save(treeByteList);

                        //字节新增后的id
                        String byteId = treeByteList.getId();


                        List<ByteFrameZu> byteFrameZuList = treeByteListVo.getByteFrameZuList();
                        if (byteFrameZuList!=null&&byteFrameZuList.size()>0){
                            for (ByteFrameZu byteFrameZu : byteFrameZuList) {
                                byteFrameZu.setByteId(byteId);
                                byteFrameZu.setIpTreeId(ipTreeId);
                                byteFrameZuService.save(byteFrameZu);

                                //新增后复用组id
                                String zuId = byteFrameZu.getId();
                                List<TreeByteListVo> children = byteFrameZu.getChildren();
                                if (!children.isEmpty()&&children.size()>0){
                                    for (TreeByteListVo child : children) {
                                        child.setPid(zuId);
                                        child.setIpTreeId(ipTreeId);
                                        List<SpecKeyValueDO> specKeyValue2 = JSONObject.parseArray(child.getExtendField(), SpecKeyValueDO.class);
                                        TreeByteList2 treeByteList2 = new TreeByteList2(child,specKeyValue2);
                                        treeByteListService2.save(treeByteList2);

                                        String treeByteList2Id = treeByteList2.getId();

                                        List<BitListVo> bitLists2 = child.getBitLists();
                                        if (bitLists2!=null&&bitLists2.size()>0){
                                            for (BitListVo bitListVo : bitLists2) {
                                                bitListVo.setByteId(treeByteList2Id);
                                                bitListVo.setIpTreeId(ipTreeId);
                                                List<SpecKeyValueDO> specKeyValueBit = JSONObject.parseArray(bitListVo.getExtendField(), SpecKeyValueDO.class);
                                                BitList Bit = new BitList(bitListVo,specKeyValueBit);
                                                bitListService.save(Bit);
                                            }
                                        }


                                    }
                                }
                            }
                        }

                        List<BitListVo> bitLists = treeByteListVo.getBitLists();
                        if (bitLists!=null&&bitLists.size()>0){
                            for (BitListVo bitListVo : bitLists) {
                                bitListVo.setByteId(byteId);
                                bitListVo.setIpTreeId(ipTreeId);
                                List<SpecKeyValueDO> specKeyValueBit = JSONObject.parseArray(bitListVo.getExtendField(), SpecKeyValueDO.class);
                                BitList Bit = new BitList(bitListVo,specKeyValueBit);
                                bitListService.save(Bit);
                            }
                        }
                    }


                    return true;
                }


            }else {
                log.error("校验不通过");
                return false;
            }
            log.error("异常");
            return false;
    }


    public boolean check(String stringXml){

        String chick = Md5Util.md5Encode(stringXml, "utf-8");

        QueryWrapper queryWrapper = new QueryWrapper<>();
      
        queryWrapper.eq("checksum",chick);
        List xmlList = this.baseMapper.selectList(queryWrapper);
        return xmlList.size()>0;
    }

    public String getChecksum(){
        long timestamp = System.currentTimeMillis();
        String s = String.valueOf(timestamp);


        Random random = new Random();
        int randomInt = random.nextInt(9000)+1000;
        return s+randomInt;
    }
}
